Repository navigation
feat(client): unify high-level client lifecycle - #48
Merged
Merged
Conversation
- give every high-level client the same lifecycle: update() returns SyncUpdate, plus wait_until_ready() and submit_and_wait() that return False only on timeout and raise for rejected, parked, or closed states - deliver token, metadata, and playback callbacks during update() and write transactions from a background thread by default - reconnect UsdPublisher from update(); disconnect() pauses reconnection - report PARKED for stage-less clients and expose unsent work, deferred layer records, and edit-target scope in ClientStatus - add SharedStageClient.resume_recovery() and playback commands - seed the EventDispatcher cursor from receiver.sync_from so snapshot continuation no longer replays full history over the snapshot - add CHANGELOG.md, enforced by check_versions.py BREAKING CHANGE: UsdReceiver.update() and UsdPublisher.update() return SyncUpdate instead of int. Transport callbacks run during update() unless callbacks_on_update=False. UsdPublisher.update() requires start(). publish_current_edit_target() keeps the snapshot while disconnected, and ManagedClient.rebind_stage() refuses unsent or unacknowledged work unless discard_unsent=True. See CHANGELOG.md for migration notes.
- state the lifecycle, error model, and host loop once in usd-native-integration.md, with the exceptions as a table - shorten the resume_recovery section and example READMEs - collapse the repeated wait_until_ready/submit_and_wait docstrings to one line; the raising rules live in raise_if_blocked - drop docstring paragraphs that restated the class docstring or docs
- replace the nine on_* callback arguments with one observer=ClientObserver; every method runs inside update() with typed payloads (AppliedBatch, StageMetadata, PlaybackState, PlaybackClaim) - add update(max_messages=) to ManagedClient and SharedStageClient so a reconnect backlog spreads over frames; local edits wait for it - resolve sender credentials once per connect attempt (token_provider) instead of reading the token file on every update() while reconnecting - default background_send to False: the Python writer waits for the GIL and adds about 6 ms per write in Python-busy hosts - add ClientStatus.can_author; connect() and flush() default to 10 s - log unreachable-server retries on one line instead of a traceback - install the Blender add-on before importing it in the reconnect test; the loaded native module made reinstalls abort halfway on Windows - trim duplicated tests, docstrings, and docs BREAKING CHANGE: high-level clients take observer= instead of on_* callback arguments; callbacks_on_update and UsdReceiver.applying_seq are removed. client.stage_metadata returns StageMetadata. connect() and flush() default to a 10 second timeout. See CHANGELOG.md for migration notes.
- remove client properties that duplicated ClientStatus fields (connection, sync, rejection, event counts, and recovery summaries) - add ClientStatus.auth_rejected to distinguish authentication from protocol rejection - read status in the blocking helpers, MCP server, usdview, and docs; keep private fast checks inside update() - restructure the 0.5.0 changelog entry around a Migrating from 0.4 section and correct entries that listed removed properties BREAKING CHANGE: read client.status instead of the removed properties; the event counts are status.pending_events, prepared_events, deferred_events, and acknowledged_events_total. CHANGELOG.md lists every replacement under (Migrating from 0.4).
- Drop duplicate assertions and a cross-client test that repeated per-client coverage; rename tests to the behavior they check. - Make RecordingObserver a plain ClientObserver subclass. - Docs: clarify flush and publish_current_edit_target, note that a ManagedClient stops receiving while its edit target is foreign, and drive recovery UI from can_author. - Changelog: list EventDispatcher.backlog_pending and NoticeEmitter.has_local_changes.
ManagedClient, SharedStageClient, UsdReceiver, and UsdPublisher build on _client_base.py. ClientBase owns lifecycle, status, observer hooks, and the credential; PublishingClientBase adds recovery, playback, and durable completion; EmitterClientBase adds emitter capture and transform coalescing. Each client keeps only its role-specific wiring and status hooks, and every phase comes from one compute_phase precedence. - ClientCredential holds the one token both roles present. EventSender and ReceiverThread take token_provider= and read it before each connection attempt. - Observer wiring moves to _observer_hooks.py as typed ObserverHooks; client_observer.py keeps only the public contract. - Rename ClientStatus.edit_target_is_shared to edit_target_is_published. - Remove UsdReceiver.layered_replay_active and client-side negotiation checks; the receiver already rejects a handshake without the requested mode. - ManagedClient.flush() raises on a rejected connection, and UsdReceiver reports CONNECTING while reconnecting, matching the other clients. - Tests: ClientCredential, phase precedence, lifecycle conformance across all four clients, and a force_handshake helper.
- A max_messages budget no longer holds local edits forever under sustained inbound traffic. BacklogHold counts the messages queued before a batch was frozen; EventDispatcher.drained_message_count replaces backlog_pending. - NoticeEmitter.has_local_changes no longer stays True after a removed local definition reveals a weaker prim. - close() delivers notifications still queued, so a token issued by the last handshake reaches host-owned storage. - close() called from an observer while events apply takes effect once the apply returns. - wait_until_ready() and submit_and_wait() raise ConnectionError when nothing will reconnect (a disconnected UsdPublisher, or a receiver with reconnect=False that lost its connection) instead of waiting forever; ReceiverThread.stopped reports the exited thread. - SharedStageClient.repair_and_resume() keeps the recovery state when repair fails validation. - Stage edits made in on_resync, or in on_applied during refresh_asset_dependency(), are not published. - ClientCredential serializes token reads and issuance; the sender rea its token only for an attempt that has time left. - SharedStageClient.status reads deferred layer keys kept current as records defer instead of rebuilding them per call. - update() is declared on ClientBase and accepts max_messages on every client; repair_and_resume() moves to EmitterClientBase. - Docs and changelog: observer threading contract, typed observer payloads in the migration notes, flush and OFFLINE behavior, can_author in examples, submit_and_wait at shutdown. - Tests: regression tests for each fix, budget tests through real drains, and 15 redundant cases removed.
With background_send, disconnect() closed the native connection of a handshake that had not published its socket yet. The resumed handshake then failed accept_hello with INVALID_PHASE and quarantined the producer session, so a later reconnect could not publish. The socket generation is now recorded at publication, and _close() only ends the published socket's connection.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BREAKING CHANGE: UsdReceiver.update() and UsdPublisher.update() return SyncUpdate instead of int. Transport callbacks run during update() unless callbacks_on_update=False. UsdPublisher.update() requires start(). publish_current_edit_target() keeps the snapshot while disconnected, and ManagedClient.rebind_stage() refuses unsent or unacknowledged work unless discard_unsent=True.